import axios, { type Method } from 'axios'
import { useUserStore } from '@/stores'
import { showToast } from 'vant'
import router from '@/router'

import { key, cs_encode, cs_decode } from './auth'

const baseURL = import.meta.env.VITE_BASE_URL
const instance = axios.create({ baseURL, timeout: 10000 })

// 白名单列表(在列跳过加密/解密)
const whiteList = ['/api/file/index', '/api/file/upload']

/**
 * 检测白名单
 */
const detect = (url: string) => {
  return whiteList.map((_url) => (url as string).includes(_url)).some((i) => i)
}

const logout = () => {
  router.push({ path: '/404' })
}

instance.interceptors.request.use(
  (config) => {
    // 检测白名单
    if (detect(config.url as string)) return config

    if (config.method === 'post') {
      // 写入token
      config.data = { ...config.data, token: useUserStore().token }
      console.log(
        'request:',
        config.url,
        JSON.parse(JSON.stringify(config.data ?? ''))
      )
      // 数据加密
      config.data = {
        _data: cs_encode({ ...(config.data as Record<string, never>) }, key),
      }
    } else {
      // 写入token
      config.params = { ...config.params, token: useUserStore().token }
      console.log(
        'request:',
        config.url,
        JSON.parse(JSON.stringify(config.params ?? ''))
      )
      // 数据加密
      config.params = {
        _data: cs_encode({ ...(config.data as Record<string, never>) }, key),
      }
    }
  },
  (err) => Promise.reject(err)
)

instance.interceptors.response.use(
  (res) => {
    if (res.status !== 200) {
      return (
        ~showToast(res.statusText || '网络异常') && Promise.reject(res.data)
      )
    }

    let response
    if (!detect(res.request.responseURL)) response = cs_decode(res.data, key)
    else response = res.data
    console.log('response:', res.request.responseURL, response)

    const { code, data, msg } = response
    switch (code) {
      case 1:
        return data
      case -10001:
        return response
      case -100:
        logout()
        break
      default:
        msg && ~showToast(msg) && Promise.reject()
    }
  },
  (err) => Promise.reject(err)
)

const request = <T>(url: string, method: Method = 'GET', data?: object) => {
  return instance.request<T, T>({
    url,
    method,
    [method.toUpperCase() === 'GET' ? 'params' : 'data']: data,
  })
}

export { baseURL, instance }

export default request
